package mylittleinvestigations;

import java.io.IOException;
import mylittleinvestigations.CaseInformation.CaseXmlReader;
import mylittleinvestigations.CaseInformation.CaseXmlWriter;

public class Line
{
    private Vector2 pointInLine;
    private Vector2 directionVector;

    public Line() { }

    public Line(Vector2 pointInLine, Vector2 directionVector)
    {
        this.pointInLine = pointInLine;
        this.directionVector = directionVector.normalize();
    }
    
    public Vector2 GetMinimalDisplacementToPoint(Vector2 point)
    {
        Line perpendicularLine = new Line(point, new Vector2(-directionVector.getY(), directionVector.getX()));
        return this.GetIntersectionPointWith(perpendicularLine).subtract(point);
    }

    public Vector2 GetIntersectionPointWith(Line otherLine)
    {
        double x = 0;
        double y = 0;

        if (this.directionVector.getX() != 0 && otherLine.directionVector.getX() != 0)
        {
            double directionVectorSlope = this.directionVector.getY() / this.directionVector.getX();
            double otherDirectionVectorSlope = otherLine.directionVector.getY() / otherLine.directionVector.getX();

            x = (otherLine.pointInLine.getY() - otherDirectionVectorSlope * otherLine.pointInLine.getX() - this.pointInLine.getY() + directionVectorSlope * this.pointInLine.getX()) / (directionVectorSlope - otherDirectionVectorSlope);
            y = directionVectorSlope * x + this.pointInLine.getY() - directionVectorSlope * this.pointInLine.getX();
        }
        else if (this.directionVector.getX() != 0)
        {
            double directionVectorSlope = this.directionVector.getY() / this.directionVector.getX();

            x = otherLine.pointInLine.getX();
            y = directionVectorSlope * x + this.pointInLine.getY() - directionVectorSlope * this.pointInLine.getX();
        }
        else if (otherLine.directionVector.getX() != 0)
        {
            double otherDirectionVectorSlope = otherLine.directionVector.getY() / otherLine.directionVector.getX();

            x = this.pointInLine.getX();
            y = otherDirectionVectorSlope * x + otherLine.pointInLine.getY() - otherDirectionVectorSlope * otherLine.pointInLine.getX();
        }

        return new Vector2(x, y);
    }

    public void SaveToXml(CaseXmlWriter writer) throws IOException
    {
        writer.StartElement("Line");
        this.SaveToXmlCore(writer);
        writer.EndElement();
    }

    protected void SaveToXmlCore(CaseXmlWriter writer) throws IOException
    {
        writer.StartElement("PointInLine");
        this.pointInLine.SaveToXml(writer);
        writer.EndElement();

        writer.StartElement("DirectionVector");
        this.directionVector.SaveToXml(writer);
        writer.EndElement();
    }

    public Line(CaseXmlReader reader)
    {
        reader.StartElement("Line");
        this.LoadFromXmlCore(reader);
        reader.EndElement();
    }

    protected final void LoadFromXmlCore(CaseXmlReader reader)
    {
        reader.StartElement("PointInLine");
        this.pointInLine = new Vector2(reader);
        reader.EndElement();

        reader.StartElement("DirectionVector");
        this.directionVector = new Vector2(reader);
        reader.EndElement();
    }
}
